package com.letoken.platform.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.letoken.platform.app.service.AppMiningDetailService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.letoken.platform.pub.enums.*;
import com.letoken.platform.pub.exception.ApiServiceException;
import com.letoken.platform.repo.admin.dao.AdminMiningInfoMapper;
import com.letoken.platform.repo.admin.po.AdminMiningInfo;
import com.letoken.platform.repo.app.dao.AppMiningDetailMapper;
import com.letoken.platform.repo.app.dao.AppMiningInfoMapper;
import com.letoken.platform.repo.app.dao.AppUserWalletMapper;
import com.letoken.platform.repo.app.po.AppMiningDetail;
import com.letoken.platform.repo.app.po.AppMiningInfo;
import com.letoken.platform.repo.app.po.AppUserAssetsHistory;
import com.letoken.platform.repo.app.po.AppUserWallet;
import com.letoken.platform.repo.performance.TeamPerformanceService;
import com.letoken.platform.repo.utlis.WebUtils;
import com.letoken.platform.repo.utlis.lock.Lock;
import com.letoken.platform.repo.utlis.lock.LockCategoryEnum;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 作者
 * @since 2023-10-16
 */
@Service
public class AppMiningDetailServiceImpl extends ServiceImpl<AppMiningDetailMapper, AppMiningDetail> implements AppMiningDetailService {


    @Resource
    private AppUserWalletMapper appUserWalletMapper;

    @Resource
    private AppMiningInfoMapper appMiningInfoMapper;

    @Resource
    private AdminMiningInfoMapper adminMiningInfoMapper;

    @Resource
    private TeamPerformanceService teamPerformanceService;

    @Override
    @Transactional
    @Lock(ce = LockCategoryEnum.USER_ID,value = "PLEDGE:TRANSFER",expire = 3l)
    public void pledge(BigDecimal amount) {
        Integer userId = WebUtils.getUserId();
        AppUserWallet appUserWallet = appUserWalletMapper.selectForUpdate(checkout(userId));
        if(appUserWallet.getAvailableBalance().compareTo(amount)<0){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_052);
        }
        AppUserWallet updateW = new AppUserWallet();
        updateW.setId(appUserWallet.getId());
        updateW.setAvailableBalance(appUserWallet.getAvailableBalance().subtract(amount));
        appUserWalletMapper.updateById(updateW);

        AppMiningInfo appMiningInfo = appMiningInfoMapper.selectOne(new QueryWrapper<AppMiningInfo>().eq("user_id",userId));
        if(ObjectUtils.isEmpty(appMiningInfo)){
            appMiningInfo = new AppMiningInfo();
            appMiningInfo.setCreateTime(LocalDateTime.now());
            appMiningInfo.setAmount(amount);
            appMiningInfo.setAccumulateIncome(BigDecimal.ZERO);
            appMiningInfo.setUserId(userId);
            appMiningInfo.insert();
        }else {
            AppMiningInfo appMiningInfo2 = new AppMiningInfo();
            appMiningInfo2.setId(appMiningInfo.getId());
            appMiningInfo2.setAmount(amount.add(appMiningInfo.getAmount()));
            appMiningInfo2.updateById();
        }

        AppMiningDetail appMiningDetail = new AppMiningDetail();
        appMiningDetail.setType(1);
        appMiningDetail.setAmount(amount);
        appMiningDetail.setUserId(userId);
        appMiningDetail.setCreateTime(LocalDateTime.now());
        appMiningDetail.insert();


        teamPerformanceService.add(TeamPerformanceTypeEnum.Minting, userId, amount);


        AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
        assetHistory.setUserId(userId);
        assetHistory.setType(TokenTransactionTypeEnum.PLEDGE.getValue());
        assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
        assetHistory.setTokenId(LetokenTokenTypeEnum.CAPA.getId());
        assetHistory.setAmount(amount.negate());
        assetHistory.setSn(appMiningDetail.getId().toString());
        assetHistory.setBalance(updateW.getAvailableBalance());
        assetHistory.setCreateTime(LocalDateTime.now());
        assetHistory.setUpdateTime(assetHistory.getCreateTime());
        assetHistory.insert();
    }

    @Override
    @Transactional
    public void mining() {
        List<AppMiningInfo> infoList = appMiningInfoMapper.getInfoList();
        AdminMiningInfo adminMiningInfo = adminMiningInfoMapper.selectById(1);
        for (AppMiningInfo appMiningInfo:infoList ) {
            BigDecimal amount = adminMiningInfo.getDailyNumber().divide(adminMiningInfo.getSumNumber(),10, RoundingMode.HALF_UP).multiply(appMiningInfo.getAmount());
            Integer walletId = appUserWalletMapper.checkoutTokenIdAndUserId(LetokenTokenTypeEnum.CAP.getId(), appMiningInfo.getUserId());
            AppUserWallet appUserWallet = appUserWalletMapper.selectForUpdate(walletId);
            if(ObjectUtils.isEmpty(appUserWallet)){
                throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_051);
            }
            AppUserWallet updateW = new AppUserWallet();
            updateW.setId(appUserWallet.getId());
            updateW.setAvailableBalance(appUserWallet.getAvailableBalance().add(amount));
            appUserWalletMapper.updateById(updateW);

            AppMiningInfo appMiningInfo2 = new AppMiningInfo();
            appMiningInfo2.setId(appMiningInfo.getId());
            appMiningInfo2.setAccumulateIncome(appMiningInfo.getAccumulateIncome().add(amount));
            appMiningInfo2.updateById();

            AppMiningDetail appMiningDetail = new AppMiningDetail();
            appMiningDetail.setCreateTime(LocalDateTime.now());
            appMiningDetail.setType(2);
            appMiningDetail.setUserId(appMiningInfo.getUserId());
            appMiningDetail.setAmount(amount);
            appMiningDetail.insert();

            AppUserAssetsHistory assetHistory = new AppUserAssetsHistory();
            assetHistory.setUserId(appMiningInfo.getUserId());
            assetHistory.setType(TokenTransactionTypeEnum.INCOME.getValue());
            assetHistory.setStatus(TokenTransactionStatusEnum.COMPLETED.getValue());
            assetHistory.setTokenId(LetokenTokenTypeEnum.CAP.getId());
            assetHistory.setAmount(amount);
            assetHistory.setSn(appMiningDetail.getId().toString());
            assetHistory.setBalance(updateW.getAvailableBalance());
            assetHistory.setCreateTime(LocalDateTime.now());
            assetHistory.setUpdateTime(assetHistory.getCreateTime());
            assetHistory.insert();
        }
    }


    private Integer checkout(Integer userId){
        Integer walletId = appUserWalletMapper.checkoutTokenIdAndUserId(LetokenTokenTypeEnum.CAPA.getId(), userId);
        if (/*ObjectUtils.isEmpty(balanceId) ||*/ ObjectUtils.isEmpty(walletId)){
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_MALL_SMS_051);
        }
        return walletId;
    }
}
